package com.wondream.example.io.nio.chat.simple;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;

/**
 * @author wangjun
 * @note NioChatServer
 * @date 2023-11-24  13:49
 */
public class NioChatServer {

    private ServerSocketChannel serverSocketChannel;

    private Selector selector;

    private static final int SERVER_PORT = 8888;

    public NioChatServer() {
        try {
            // 1.得到ServerSocketChannel
            serverSocketChannel = ServerSocketChannel.open();
            // 2.得到Selector
            selector = Selector.open();
            // 3.绑定端口号
            serverSocketChannel.bind(new InetSocketAddress(8888));
            // 4.设置非阻塞
            serverSocketChannel.configureBlocking(false);
            // 5.ServerSocketChannel注册到Selector
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            info("Chat Server is ready");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start() {
        try {
            while (true) {
                // 1.监听客户端
                if (selector.select(2000) == 0) {
                    System.out.println("Server:没有客户端连接，干点别的");
                    continue;
                }
                // 2.根据selectionKey处理事件
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    if (selectionKey.isAcceptable()) {
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                        info(socketChannel.getRemoteAddress().toString().substring(1) + "上线了...");
                    }
                    if (selectionKey.isReadable()) {
                        readMsg(selectionKey);
                    }
                    if (selectionKey.isWritable()) {

                    }
                    // 3.手动从集合中移除当前key，防止重复处理
                    iterator.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void readMsg(SelectionKey selectionKey) throws Exception {
        SocketChannel channel = (SocketChannel) selectionKey.channel();
        Selector selector1 = selectionKey.selector();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        // 读取数据
        int readNum = channel.read(buffer);
        if (readNum < 1) {
            return;
        }
        // 打印数据
        String msg = new String(buffer.array());
        info(msg);
        // 广播数据
        broadCast(channel, msg);
    }

    private void broadCast(SocketChannel channel, String msg) throws Exception {
        info("服务器发送了广播...");
        for (SelectionKey selectionKey : selector.keys()) {
            if (selectionKey.channel() instanceof ServerSocketChannel) {
                continue;
            }
            SocketChannel targetChannel = (SocketChannel) selectionKey.channel();
            if (channel == targetChannel) {
                continue;
            }
            ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes(StandardCharsets.UTF_8));
            targetChannel.write(byteBuffer);
        }
    }

    private void info(String msg) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(String.format("【%s】-> %s", sdf.format(new Date()), msg)
        );
    }

    public static void main(String[] args) {
        new NioChatServer().start();
    }
}
